package com.sky.aop;

import com.sky.mapper.admin.EmployeeMapper;
import com.sky.utils.ParseJWTGetId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@RequiredArgsConstructor
@Aspect
@Component
public class AdminAddOrUpdate {

    private final ParseJWTGetId parseJWTGetId;
    private final EmployeeMapper employeeMapper;

    private final Map<Class<?>, Map<String, Method>> methodCache = new ConcurrentHashMap<>();

    // 缓存用户信息，避免重复查询数据库
    private final Map<Integer, String> userCache = new ConcurrentHashMap<>();

    /**
     * 创建时间，创建人，更新时间，更新人
     * 专门处理新增操作
     */
    @Before("execution(* com.sky.service.admin.*.save(..)) || " +
            "execution(* com.sky.service.admin.*.mySave(..)) || " +
            "execution(* com.sky.service.admin.*.add*(..)) || " +
            "execution(* com.sky.service.admin.*.myAdd*(..)) || " +
            "execution(* com.sky.service.admin.*.myInsert*(..)) || " +
            "execution(* com.sky.mapper.admin.*.insert*(..))")
    public void setCreateTimeAndUser(JoinPoint joinPoint) {
        try {
            Object entity = getFirstEntity(joinPoint);
            if (entity == null) return;

            Integer empId = parseJWTGetId.getEmpId();

            // 设置创建相关字段
            invokeSetterSafely(entity, "setCreateTime", LocalDateTime.now());
            invokeSetterSafely(entity, "setUpdateTime", LocalDateTime.now());
            invokeSetterSafely(entity, "setCreateUser", empId);
            invokeSetterSafely(entity, "setUpdateUser", empId);

            log.debug("设置创建信息完成: {}", entity.getClass().getSimpleName());

        } catch (Exception e) {
            log.warn("设置创建信息失败: {}", e.getMessage());
        }
    }

    /**
     * 修改时间，修改人
     * 专门处理更新操作
     */
    @Before("execution(* com.sky.service.admin.*.update*(..)) || " +
            "execution(* com.sky.service.admin.*.myUpdate*(..)) || " +
            "execution(* com.sky.service.admin.*.modify*(..)) || " +
            "execution(* com.sky.service.admin.*.myModify*(..)) || " +
            "execution(* com.sky.mapper.admin.*.myUpdate*(..)) || " +
            "execution(* com.sky.mapper.admin.*.update*(..))")
    public void setUpdateTimeAndUser(JoinPoint joinPoint) {
        try {
            Object entity = getFirstEntity(joinPoint);
            if (entity == null) return;

            // 设置更新相关字段
            invokeSetterSafely(entity, "setUpdateTime", LocalDateTime.now());
            invokeSetterSafely(entity, "setUpdateUser", parseJWTGetId.getEmpId());

            log.debug("设置更新信息完成: {}", entity.getClass().getSimpleName());

        } catch (Exception e) {
            log.warn("设置更新信息失败: {}", e.getMessage());
        }
    }

    /**
     * 安全地获取第一个实体参数
     */
    private Object getFirstEntity(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            log.debug("方法没有参数: {}", joinPoint.getSignature().getName());
            return null;
        }

        Object firstArg = args[0];
        if (firstArg == null) {
            log.debug("第一个参数为null: {}", joinPoint.getSignature().getName());
            return null;
        }

        return firstArg;
    }

    /**
     * 安全调用setter方法
     */
    private void invokeSetterSafely(Object target, String methodName, Object value) {
        try {
            Method method = getMethod(target.getClass(), methodName, value.getClass());
            if (method != null) {
                method.invoke(target, value);
            }
        } catch (Exception e) {
            log.trace("调用方法 {} 失败: {}", methodName, e.getMessage());
        }
    }

    /**
     * 获取方法对象（带缓存）
     */
    private Method getMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
        return methodCache.computeIfAbsent(clazz, k -> new HashMap<>()).computeIfAbsent(methodName + paramTypes.length, k -> {
            try {
                return clazz.getMethod(methodName, paramTypes);
            } catch (NoSuchMethodException e) {
                return null;
            }
        });
    }




    /**
     * 清理用户缓存（可选，用于用户信息变更时）
     */
    public void clearUserCache(Integer empId) {
        if (empId != null) {
            userCache.remove(empId);
        }
    }

    /**
     * 清理所有缓存（可选）
     */
    public void clearAllCache() {
        userCache.clear();
        methodCache.clear();
    }
}